package gbench.appdemo.mall.mvc;

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.BufferedImageHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * MVC 的基础配置
 * @author gbench
 *
 */
@Configuration 
@EnableWebMvc 
public class MvcConfig implements WebMvcConfigurer { 
    
    /**
     * 图片信息的转换
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new BufferedImageHttpMessageConverter());
    }

    /**
     * 
     * @param className
     * @return
     */
    public static Class<?> forName(String className) {
        try {
            return Class.forName(className.replaceAll("/|\\\\", "."));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 获取所有文件列表
     * @param rootFile
     * @param fileList
     * @return class 文件名，不带哟class
     * @throws IOException
     */
    public static List<String> listFiles(File rootFile,List<String> fileList) throws IOException{
        final var allFiles = rootFile.listFiles();
        for(File file : allFiles){
            if(file.isDirectory()){
                listFiles(file, fileList);
            }else{
                final var path = file.getCanonicalPath();
                final var clazz = path.substring(path.indexOf("classes")+8);
                fileList.add(clazz.replace("//", ".").substring(0,clazz.lastIndexOf(".")));
            }//if
        }//for
        return fileList;
    }
 
    /**
     * 获取子类型
     * @param baseClazz 基本类型
     * @param cs 回调函数
     */
    public void handleAllSubClasses(final String pkgname,final Class<?> baseClazz, final Consumer<Class<?>>cs) {
        final var rootPath = this.getClass().getClassLoader().getResource(pkgname).getFile();
        final var  rootFile = new File(rootPath.replace("%20", " "));
        try {
            listFiles(rootFile, new LinkedList<String>()).stream()
            .map(MvcConfig::forName)
            .filter(e->e!=null)
            .filter(baseClazz::isAssignableFrom)
            .forEach(cs);
        }catch(Exception e) {
            e.printStackTrace();
        }// try
    }

    /**
     * 参数处理子
     */
    @Override 
    public void addArgumentResolvers(final List<HandlerMethodArgumentResolver> resolvers) { 
        final var pkgname = this.getClass().getPackageName().replace('.', '/'); // 提取当前目录下的 resolver class
        handleAllSubClasses(pkgname,HandlerMethodArgumentResolver.class,clazz->{
            try {
                final var ctor = clazz.getConstructor();
                final var resolver = (HandlerMethodArgumentResolver)ctor.newInstance();
                if(resolver==null)return;
                resolvers.add(resolver); 
            } catch (Exception e) {
                e.printStackTrace();
            }// try
        });
    } 
}